package cn.itcast.lucene;

import org.apache.lucene.document.Document;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryparser.classic.MultiFieldQueryParser;
import org.apache.lucene.queryparser.classic.ParseException;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.*;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.junit.Test;
import org.wltea.analyzer.lucene.IKAnalyzer;

import java.io.File;
import java.io.IOException;

public class LuceneIndexQueryTest {

    @Test
    public void testQueryIndex() throws IOException, ParseException {



        //查询的字段，要对应的分词器
        QueryParser queryParser = new QueryParser("title",new IKAnalyzer());

        //查询的内容
        Query query = queryParser.parse("谷歌");


        search(query);
    }

    @Test
    public void testMutilFieldQuery() throws IOException, ParseException {


        //查询的字段，要对应的分词器 id=3  title  include 3
        MultiFieldQueryParser queryParser = new MultiFieldQueryParser(new String[]{"id","title"},new IKAnalyzer());

        //查询的内容
        Query query = queryParser.parse("3");


        search(query);

    }


    @Test
    public void testTermQuery() throws IOException, ParseException {

        Query query = new TermQuery(new Term("title","谷歌地图"));

        search(query);

    }

    /*
     * 测试通配符查询
     * 	? 代表一个任意字符
     * 	* 代表0个或多个任意字符
     */
    @Test
    public void testWildCardQuery() throws IOException, ParseException {

        Query query = new WildcardQuery(new Term("title","*人"));

        search(query);

    }

    //最大编辑距离（可更改几次），默认2，取值0-2，赋值越界报错
    @Test
    public void testFuzzyQuery() throws IOException, ParseException {

        Query query = new FuzzyQuery(new Term("title","facabooc"),1);

        search(query);

    }


    //数值范围查询
    @Test
    public void testNumericRangeQuery() throws IOException, ParseException {

        //第一个参数表示查询字段，第二个参数表示最小值，最大值，是否包含最小值，最大值
        Query query = NumericRangeQuery.newLongRange("id",1L,3L,false,false);

        search(query);

    }


    /**
     * MUST VS MUST  && 与   SHOULD VS SHOULD|| 或  ！ MUST_NOT
     *
     *
     * @throws IOException
     * @throws ParseException
     */

    @Test
    public void testBooleanQuery() throws IOException, ParseException {

        //第一个参数表示查询字段，第二个参数表示最小值，最大值，是否包含最小值，最大值
        Query query1 = NumericRangeQuery.newLongRange("id",1L,3L,true,true);
        Query query2 = NumericRangeQuery.newLongRange("id",2L,4L,true,true);


        BooleanQuery query = new BooleanQuery();

        query.add(query1, BooleanClause.Occur.MUST);
        query.add(query2, BooleanClause.Occur.MUST_NOT);

        search(query);

    }





    public void search(Query query) throws IOException, ParseException {
        //找到索引的地址
        Directory directory = FSDirectory.open(new File("indexDir"));

        //创建索引的读取对象
        IndexReader indexReader = DirectoryReader.open(directory);

        //创建搜索对象
        IndexSearcher indexSearcher = new IndexSearcher(indexReader);


        //search，两个参数分别表示查询条件对象以及要查询的个数（前n条 topN）
        //执行查询，返回前n条文档数据集合
        TopDocs search = indexSearcher.search(query, Integer.MAX_VALUE);

        //命中的条目数
        int totalHits = search.totalHits;

        System.out.println("totalHits = " + totalHits);

        //所有的得分文档数组
        ScoreDoc[] scoreDocs = search.scoreDocs;

        for (ScoreDoc scoreDoc : scoreDocs) {
            //得分
            float score = scoreDoc.score;

            //文档ID
            int docID = scoreDoc.doc;

            //根据文档的id找到对应的文档
            Document document = indexSearcher.doc(docID);


            String id = document.get("id");
            String title = document.get("title");

            System.out.println("得分： " + score + " id:" + id + " title:" + title);
        }
    }
}
